﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using GarboChess;
using System.Windows.Threading;
using Microsoft.Phone.Shell;
using System.Diagnostics;

namespace WP7Chess
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Position position = new Position();
        private Searcher searcher;
        //private JScriptPlayer jscriptPlayer;
        private DispatcherTimer timer = new DispatcherTimer();
        private bool isGameOver = false;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            this.position.ResetBoard();

            this.searcher = new Searcher(this.position);
            this.searcher.AllottedTime = 200;

            this.chessBoard.UserMove += this.OnUserMove;
            this.chessBoard.AnimationCompleted += this.OnChessBoardAnimationCompleted;

            this.timer.Interval = TimeSpan.FromMilliseconds(10);
            this.timer.Tick += this.OnTimerTick;

            this.Loaded += this.OnRootControlLoaded;

            VisualStateManager.GoToState(this, "PageShown", false);
        }

        void UpdatePlayerInfo()
        {
            tbPlayerOneInfo.Text = GetPlayerInfo(App.GameSetup.Player1);
            tbPlayerTwoInfo.Text = GetPlayerInfo(App.GameSetup.Player2);
        }

        private string GetPlayerInfo(PlayerType playerType)
        {
            switch (playerType)
            {
                case PlayerType.CSharp:
                    return "Computer (C#)";
                case PlayerType.Human:
                    return "Human";
                case PlayerType.JavaScript:
                    return "Computer (JavaScript)";
                default:
                    return string.Empty;
            }
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            if (PhoneApplicationService.Current.State.ContainsKey("moves"))
                this.position = (Position)PhoneApplicationService.Current.State["moves"];

            UpdatePlayerInfo();

            base.OnNavigatedTo(e);
            
            VisualStateManager.GoToState(this, "PlayerInfoVisible", true);
            VisualStateManager.GoToState(this, "PageNormal", true);
        }

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            PhoneApplicationService.Current.State["moves"] = this.position;

            UpdatePlayerInfo();

            base.OnNavigatedFrom(e);

            VisualStateManager.GoToState(this, "PlayerInfoVisible", true);
        }

        protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            PhoneApplicationService.Current.State["moves"] = this.position;

            base.OnNavigatingFrom(e);
        }

        private void OnRootControlLoaded(object sender, RoutedEventArgs e)
        {
            this.chessBoard.Position = this.position;
        }

        private void OnUserMove(ushort move)
        {
            this.position.MakeMove(move);
            this.chessBoard.UpdateForNewPosition();
        }

        private void OnChessBoardAnimationCompleted()
        {
            // ushort moves = HtmlPage.Window.Invoke("GenerateValidMoves");


            if (this.position.GenerateValidMoves().Count == 0)
            // if (this.jscriptPlayer.ValidMoves().Count == 0)
            {
                if (this.isGameOver)
                {
                    return;
                }

                this.isGameOver = true;
                // Game over state
                
                var result = MessageBox.Show(string.Format("{0} player wins!", this.position.ToMove == 0 ? "White" : "Black"), "Game Over", MessageBoxButton.OKCancel);

                if (result == MessageBoxResult.OK)
                {
                    RestartGame();
                }
            }
            else
            {
                this.DoAITurn();
            }
        }

        private void RestartGame()
        {
            this.isGameOver = false;

            this.position.ResetBoard();
            this.chessBoard.UpdateForNewPosition();

            VisualStateManager.GoToState(this, "PlayerInfoVisible", true);
        }

        private void OnSelectorSelectionChanged(object sender, EventArgs e)
        {
            this.DoAITurn();
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            this.timer.Stop();
            this.chessBoard.UpdateForNewPosition();
        }

        private void DoAITurn()
        {
            int color = this.position.ToMove;
            var selector = color == 0 ? App.GameSetup.Player2 : App.GameSetup.Player1; // TODO: this.blackSelector : this.whiteSelector;

            if (selector == PlayerType.Human)
            {
                //this.UpdateNodesSec(color, "Human", 3, 1000);
                return;
            }

            if (selector == PlayerType.CSharp)
            {
                this.position.MakeMove(this.searcher.Search());
                var strColor = color == 0 ? "C# (black)" : "C# (white)";
                this.UpdateNodesSec(color, strColor, this.searcher.QNodeCount + this.searcher.NodeCount, this.searcher.AllottedTime);
            }
            //else if (selector.SelectedPlayer == 2)
            //{
            //    this.jscriptPlayer.Fen = this.position.GetFen();
            //    this.position.MakeMove(this.jscriptPlayer.MakeMove());
            //    this.UpdateNodesSec(color, "JS", this.jscriptPlayer.Nodes, this.jscriptPlayer.Time);

            //}

            this.timer.Start();
        }

        private void UpdateNodesSec(int color, string aiName, int nodes, int time)
        {
            long nodesSecVal = ((long)nodes * 1000) / time;
            nodesSec.Text = string.Concat(aiName, ": ", nodesSecVal.ToString());
            //if (color == 0)
            //{
            //    this.blackNodesSec.Text = nodesSec.ToString();
            //    this.blackNodesTitle.Text = aiName + " Nodes/Sec.";
            //}
            //else
            //{
            //    this.whiteNodesSec.Text = nodesSec.ToString();
            //    this.whiteNodesTitle.Text = aiName + " Nodes/Sec.";
            //}
        }

        private void About_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/AboutPage.xaml", UriKind.Relative));
        }

        private void Settings_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/SettingsPage.xaml", UriKind.Relative));
        }

        private void Undo_Click(object sender, EventArgs e)
        {
            position.UnmakeMove(0);
        }

        private void NewGame_Click(object sender, EventArgs e)
        {
            var restart = MessageBox.Show("Start the new game?", "New Game", MessageBoxButton.OKCancel);

            if (restart == MessageBoxResult.OK)
                RestartGame();
       }

        private void playerInfoVisibleStoryboard_Completed(object sender, EventArgs e)
        {
            VisualStateManager.GoToState(this, "PlayerInfoHidden", true);
        }
    }
}